package com.xykj.enterprise.wechat.util.other;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

/**
 * @author Feng Chen
 */
public class CodeUtil {

    private static final List<Character> CLIST = Arrays.asList(
            'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N',
            'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't', 'u',
            'v', 'w', 'x', 'y', 'z'
    );

    private static final int DIMENS = CLIST.size();

    private static final int LEN = 8;
    private static final String PREFIX = "Fy";

    /**
     * 编码
     *
     * @param num
     * @return
     */
    public static String encode(long num) {
        String str = encodeImpl(num);
        int len = str.length();
        StringBuilder builder = new StringBuilder();
        builder.append(PREFIX);
        if (len < 5) {
            for (int i = 0; i < LEN - len; i++) {
                builder.append("A");
            }
        }
        builder.append(str);
        return builder.toString();
    }

    /**
     * 解码
     *
     * @param str
     * @return
     */
    public static int decode(String str) {
        if (str.startsWith(PREFIX)) {
            str = str.replaceFirst(PREFIX, "");
        }
        return decodeImpl(str);
    }


    // SECTION : INNER HELPER

    private static String encodeImpl(long num) {
        if (num < 0) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        if (num > DIMENS) {
            builder.append(encodeImpl(num / DIMENS));
        }
        int least = (int) (num % DIMENS);
        builder.append(CLIST.get(least));
        return builder.toString();
    }

    private static int decodeImpl(String str) {
        BigDecimal num = BigDecimal.valueOf(0);
        char[] chs = str.toCharArray();
        int length = chs.length;
        for (char c : chs) {
            if (CLIST.indexOf(c) < 0) {
                return 0;
            }
            num = num.add(
                    BigDecimal.valueOf(CLIST.indexOf(c))
                            .multiply(
                                    BigDecimal.valueOf(Math.pow(DIMENS, (--length)))
                            )
            );
        }
        return num.intValue();
    }

}
